package cn.tedu.mybatis.utils;

import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;

import java.io.IOException;

/**
 * SqlSession工具类
 * 封装SqlSession对象
 * 该类主要用于简化SqlSession的创建和管理过程
 * 通过该工具类，可以避免在每次需要执行数据库操作时重复创建和关闭SqlSession
 */
public class SqlSessionUtil {
    // 私有构造方法，防止实例化
    private SqlSessionUtil(){}
    // 单例模式，用于存储SqlSessionFactory实例
    private static SqlSessionFactory sqlSessionFactory;
    // 静态代码块，用于初始化SqlSessionFactory
    static{
        try {
            // 从配置文件中构建SqlSessionFactory
            sqlSessionFactory = new SqlSessionFactoryBuilder().build(Resources.getResourceAsStream("mybatis-config.xml"));
        } catch (IOException e) {
            // 如果配置文件读取失败，则抛出运行时异常
            throw new RuntimeException(e);
        }
    }
    //全局的，服务器级别的，一个服务器当中定义一个即可
    private static ThreadLocal<SqlSession> local = new ThreadLocal<>();
    /**
     * 获取会话对象
     * 打开并返回一个SqlSession实例
     * 此方法用于获取SqlSession，以便进行数据库操作
     * @return 返回会话对象，SqlSession实例，用于执行SQL语句和进行事务管理
     */

    public static SqlSession openSession(){
        SqlSession sqlSession = local.get();
        if (sqlSession == null){
            sqlSession  = sqlSessionFactory.openSession();
            //将sqlSession独享绑定到当前线程上
            local.set(sqlSession);
        }
        return sqlSession;
    }
    /**
     * 关闭sqlSession对象（从当前线程中移除sqlSession对象）
     */
    public static void close(SqlSession sqlSession){
        if (sqlSession != null){
            sqlSession.close();
            //移除sqlSession对象，和当前线程的绑定关系
            //因为Tomcat服务器支持线程池，也就是说用过的线程对象T1，可能下一次还回使用这个T1线程
            local.remove();
        }
    }
}
